package com.bonc.apim.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bonc.apim.constant.BaseConstant;
import com.bonc.apim.dao.PublishDao;
import com.bonc.apim.dao.RecordDao;
import com.bonc.apim.entity.JsonResult;
import com.bonc.apim.entity.Publish;
import com.bonc.apim.entity.Record;
import com.bonc.apim.utils.WebClientUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;

@Controller
@RequestMapping("/publish")
public class PublishController {
    
    private static final Log log = LogFactory.getLog(PublishController.class);
    
    @Value("${publishModelKey}")
    private String publishModelKey;
    
    @Value("${bpmStartProcessURL}")
    private String bpmStartProcessURL;
    
    @Value("${bpmCompleteTaskURL}")
    private String bpmCompleteTaskURL;
    
    @Value("${bpmIframeNameUrl}")
    private String bpmIframeNameUrl;

    @Value("${bpmTrackURL}")
    private String bpmTrackURL;

    @Value("${apimPublishURL}")
    private String apimPublishURL;

    @Value("${tenantId}")
    private String tenantId;

    @Value("${iframeNameForBCMUrl}")
    private String iframeNameForBCMUrl;

    @Value("${bconsoleURL}")
    private String bconsoleURL;

    @Value("${enableBconsole}")
    private boolean enableBconsole;

    @Value("${portalURL}")
    private String portalURL;

    @Autowired
    private PublishDao publishDao;

    @Autowired
    private RecordDao recordDao;

    /**
     * 发布API审批-启动流程
     */
    @RequestMapping("/startProcess")
    @ResponseBody
    public Object startProcess(@ModelAttribute Publish publish, HttpServletRequest request, HttpServletResponse response, String callback) {

        long startTime = new Date().getTime();
        log.info("startPubProcess");
        String providerName = publish.getProviderName();
        String tenant_id = tenantId;
        String loginId = publish.getLoginId();
        int[] code = {BaseConstant.API_APPROVING, BaseConstant.API_APPROVED_LEVEL_A_PASS };
        /* 如果API状态不是审核中，则重新启动订阅流程 */
        List<Publish> subInfoList = publishDao.findByProviderNameAndApiNameAndVersionAndContextAndTierAndProtocolAndApiApproveStatusIn(providerName,
            publish.getApiName(), publish.getVersion(), publish.getContext(), publish.getTier(), publish.getProtocol(), code);
        if (!CollectionUtils.isEmpty(subInfoList)) {
            return buildReturn(callback, new JsonResult("流程正在审核中", BaseConstant.RETURN_CODE_EXISTED));
        }

        publish.setApiApproveStartTime(new Date());
        publish.setApiApproveStatus(BaseConstant.API_APPROVING);// 状态
        publishDao.save(publish);
        long saveTime = new Date().getTime();
        log.info("save sub date cost time： = " + (saveTime - startTime));
        /** 获取bpm流程启动返回流程实例id */
        String jsonData = null;
        try {
            jsonData = WebClientUtil.doGet(bpmStartProcessURL + "?modelKey=" + publishModelKey + "&loginId=" + loginId + "&pubInfoId="
                + publish.getId() + "&providerName=" + providerName + "&tenant_id=" + tenant_id + "&providerTenant=" + publish.getTenantId(), null);
            // TODO 下次修改时在启动流程时添加脚本调用url地址方便修改
            JSONObject jsonObject = JSON.parseObject(jsonData);
            publish.setProInsId((String) jsonObject.get("processInstanceId"));
            long sendTime1 = new Date().getTime();
            log.info("start Process： = " + (sendTime1 - saveTime));
            publishDao.save(publish);
            log.info("tenant_id=" + tenant_id);

            if (enableBconsole) {
                String svcName = "API发布审核";
                String jsonData1 = WebClientUtil
                    .doGet(bconsoleURL + "/v1/tenantId/" + tenant_id + "/loginId/" + loginId + "/bpmInstance" + "?svcCode=" + publishModelKey
                        + "&svcName=" + URLEncoder.encode(svcName, "utf-8") + "&processInstanceId=" + publish.getProInsId() + "&expand1={\"levelNum\":1,\"approvalOrlookFlag\":\"approval\"}", null);

                // JSONObject jsonObject1 = JSON.parseObject(jsonData1);
                log.debug("enableBconsole-jsonObject=" + jsonData1);
                long sendTime2 = new Date().getTime();
                log.info("Bconsole cast time： = " + (sendTime2 - sendTime1));
            }
        } catch (Exception e) {
            // 流程启动失败后，删除添加的数据
            publishDao.delete(publish.getId());
            log.error("the process start is fail,response:" + jsonData, e);
            return buildReturn(callback, new JsonResult("审核流程启动失败，请联系管理员", BaseConstant.RETURN_CODE_ERROR));
        }
        return buildReturn(callback, new JsonResult("新的流程启动成功", BaseConstant.RETURN_CODE_OK));
    }

    /**
     * 发布API审批-办理审核流程
     * 一级审核-租户管理员审核
     * 二级审核-运营管理员审核
     *
     * @param flowInstId
     *            流程实例id
     * @param taskId
     *            当前流程任务id
     * @param approvalOrlookFlag
     *            办理或办理成功后查看 标志
     * @return
     */
    @RequestMapping("/approveApi")
    public String approveApi(String flowInstId, String taskId, String approvalOrlookFlag, String user, String tenant_id, String task_key,
        int levelNum, Model model) {

        log.info("approveApi="+ levelNum);
        // System.out.println("levelNum = " + levelNum);
        Publish publish = publishDao.findByProInsId(flowInstId);
        List<Record> recordList = recordDao.findByProInsId(flowInstId);
        // tenant_id = (subscribMode==0?tenant_id:tenantId);
        model.addAttribute("proInsId", flowInstId);
        model.addAttribute("taskId", taskId);
        model.addAttribute("publish", publish);
        model.addAttribute("recordList", recordList);
        model.addAttribute("loginUser", user);
        model.addAttribute("levelNum", levelNum);
        log.debug(model.toString());
        /** 判断bpm工单是跳往办理页面或者查看页面 */
        if ("approval".equals(approvalOrlookFlag)) {
            return "apipublishapproval.jsp";
        } else if ("look".equals(approvalOrlookFlag)) {
            return "apipublishapplyscan.jsp";
        }
        return "";
    }

    /**
     * 发布API审批-完成任务节点
     *
     * @param proInsId
     *            流程id
     * @param taskId
     *            任务id
     * @param approvalSumup
     *            提交同意(1 pass)，不同意(0 nopass)
     * @param remark
     *            审批意见
     * @return
     */
    @RequestMapping("/completeTask")
    public String completeTask(String proInsId, String taskId, String approvalSumup, String remark, String user, String levelNum, String secretData) {

        log.info("completeTask  === " + levelNum);
        Publish publish = publishDao.findByProInsId(proInsId);
        if (secretData == null) {
            secretData = "2";
        }
        publish.setSecretData(Integer.valueOf(secretData));//
        publishDao.save(publish);

        if (BaseConstant.APPROVAL_PASS == Integer.valueOf(approvalSumup)) {
            String ru = WebClientUtil.doGet(bpmCompleteTaskURL + "?taskId=" + taskId + "&action=pass" + "&loginId=" + user + "&tenant_id=" + tenantId,
                null);
            JSONObject jsonResult = JSON.parseObject(ru);
//            if (!jsonResult.getBooleanValue("success")) {
//                return "redirect:" + portalURL;
//            }
            log.info("completeTask1 levelNum = " + levelNum);
            if (publish.getApiApproveStatus()==3){
                publish.setApiApproveStatus(BaseConstant.API_APPROVED_LEVEL_B_PASS);
            } else {
                publish.setApiApproveStatus(BaseConstant.getPassConstant(levelNum));// 更新API审核状态:完成
            }
            publishDao.save(publish);
            // 给bconsole返回状态
            if (enableBconsole) {
                String jsonData = WebClientUtil.doGet(bconsoleURL + "/v1/tenantId/" + tenantId + "/loginId/" + user + "/bpmProcess"
                    + "?agreement=1&processInstanceId=" + publish.getProInsId() + "&expand1=" + "{\"levelNum\":"+("1".equals(levelNum)?"2":levelNum)+",\"approvalOrlookFlag\":\"approval\"}", null);

                // JSONObject jsonObject1 = JSON.parseObject(jsonData);
                log.debug("enableBconsole-jsonObject=" + jsonData);
            }
            addRecord(publish, taskId, remark, BaseConstant.APPROVAL_PASS, user);
        } else if (BaseConstant.APPROVAL_NOPASS == Integer.valueOf(approvalSumup)) {
            String ru = WebClientUtil
                .doGet(bpmCompleteTaskURL + "?taskId=" + taskId + "&action=nopass" + "&loginId=" + user + "&tenant_id=" + tenantId, null);
            JSONObject jsonResult = JSON.parseObject(ru);
//            if (!jsonResult.getBooleanValue("success")) {
//                return "redirect:" + portalURL;
//            }
            log.info("completeTask2 levelNum = " + levelNum);
            if (publish.getApiApproveStatus() == 2){
                publish.setApiApproveStatus(BaseConstant.API_APPROVED_LEVEL_B_NOPASS);
            } else {
                publish.setApiApproveStatus(BaseConstant.getNoPassConstant(levelNum));// 更新API审核状态:不同意
            }
            // 给bconsole返回状态
            if (enableBconsole) {
                String jsonData = WebClientUtil.doGet(bconsoleURL + "/v1/tenantId/" + tenantId + "/loginId/" + user + "/bpmProcess"
                    + "?agreement=0&processInstanceId=" + publish.getProInsId() + "&expand1=" + "{\"levelNum\":"+("1".equals(levelNum)?"2":levelNum)+",\"approvalOrlookFlag\":\"approval\"}", null);

                // JSONObject jsonObject1 = JSON.parseObject(jsonData);
                log.debug("enableBconsole-jsonObject=" + jsonData);
            }
            publishDao.save(publish);
            addRecord(publish, taskId, remark, BaseConstant.APPROVAL_NOPASS, user);
        }
        return "redirect:" + portalURL;
    }

    /**
     * 发布API审批-调用脚本 通过
     *
     * @param pubInfoId
     *            主键
     * @return
     */
    @RequestMapping("/apimInvokePass")
    public void apimInvokePass(long pubInfoId) {

        log.info("bpm js process  invoke: pass " + pubInfoId);
        Publish publish = publishDao.findById(pubInfoId);
        try {
            String url = apimPublishURL + "&name=" + URLEncoder.encode(publish.getApiName(), "UTF-8") + "&version=" + publish.getVersion()
                + "&provider=" + publish.getProviderName() + "&context=" + publish.getContext() + "&userName=" + publish.getLoginId() + "&tenantId="
                + publish.getTenantId() + "&secret=" + publish.getSecretData() + "&status=Publish&result=pass&pinsid=" + publish.getProInsId();
            String jsonData = WebClientUtil.doGet(url, null);
            log.debug("apim invoke request---------------------" + url);
            log.debug("apim invoke response--------------------" + jsonData);
        } catch (UnsupportedEncodingException e) {
            log.error("apim encode api name error");
            // TODO Auto-generated catch block
            e.printStackTrace();
            // return "{\"code\":500}";
        }
        // return "{\"code\":200}";//iframeNameForBCMUrl;// http://bpm:8080/bpm/task-list.jsp
    }

    /**
     * 发布API审批-脚本调用 不通过
     *
     * @return
     */
    @RequestMapping("/apimInvokeNoPass")
    public void apimInvokeNoPass(long pubInfoId, int level) {

        log.info("bpm js process  invoke: nopass " + pubInfoId);
        Publish publish = publishDao.findById(pubInfoId);
        try {
            String url = apimPublishURL + "&name=" + URLEncoder.encode(publish.getApiName(), "UTF-8") + "&version=" + publish.getVersion()
                + "&provider=" + publish.getProviderName() + "&context=" + publish.getContext() + "&userName=" + publish.getLoginId() + "&tenantId="
                + publish.getTenantId() + "&secret=" + publish.getSecretData() + "&status=Publish&result=nopass&pinsid=" + publish.getProInsId();
            String jsonData = WebClientUtil.doGet(url, null);
            log.debug("apim invoke request---------------------" + url);
            log.debug("apim invoke response--------------------" + jsonData);
        } catch (UnsupportedEncodingException e) {
            log.error("apim encode api name error");
            // TODO Auto-generated catch block
            e.printStackTrace();
            // return "{\"code\":500}";
        }

        // return "{\"code\":200}";
    }
    
    /**
     * 发布API审批-添加流程记录
     * 
     * @param publish
     * @param taskId
     * @param remark
     * @return
     */
    private void addRecord(Publish publish, String taskId, String remark, int status, String loginUser) {
        
        log.info("addRecord");
        Record record = new Record();
        record.setProInsId(publish.getProInsId());
        record.setApprover(loginUser);
        record.setTaskId(taskId);
        record.setView(remark);
        record.setCreateDate(new Date());
        record.setRecordApproveStatus(status);
        recordDao.save(record);
    }
    
    /**
     * 发布API审批-判断返回json对象，jsop
     * 
     * @param callback
     * @param jsonResult
     * @return
     */
    private Object buildReturn(String callback, JsonResult jsonResult) {
        
        log.info("buildReturn");
        if (!StringUtils.isEmpty(callback)) {
            return callback + "(" + JSON.toJSONString(jsonResult) + ")";
        }
        return jsonResult;
    }
}
